#include "wx/wxprec.h"
#include "wx/stopwatch.h"

#if defined(__VISAGECPP__) && !defined(HAVE_FTIME)
#define HAVE_FTIME
#  if __IBMCPP__ >= 400
#  define ftime(x) _ftime(x)
#  endif
#endif

#include <time.h>


#include <sys/types.h>      // for time_t

#if defined(HAVE_GETTIMEOFDAY)
#include <sys/time.h>
#include <unistd.h>
#elif defined(HAVE_FTIME)
#include <sys/timeb.h>
#endif

#ifdef HAVE_GETTIMEOFDAY
#ifdef WX_GETTIMEOFDAY_NO_TZ
struct timezone;
#define wxGetTimeOfDay(tv, tz)      gettimeofday(tv)
#else
#define wxGetTimeOfDay(tv, tz)      gettimeofday((tv), (tz))
#endif
#endif // HAVE_GETTIMEOFDAY

void wxStopWatch::Start( long t ) {
  m_t0 = wxGetLocalTimeMillis() - t;
  m_pause = 0;
  m_pauseCount = 0;
}

long wxStopWatch::GetElapsedTime() const {
  return ( wxGetLocalTimeMillis() - m_t0 ).GetLo();
}

long wxStopWatch::Time() const {
  return m_pauseCount ? m_pause : GetElapsedTime();
}

static wxLongLong wxStartTime = 0l;

void wxStartTimer() {
  wxStartTime = wxGetLocalTimeMillis();
}

// Returns elapsed time in milliseconds
long wxGetElapsedTime( bool resetTimer ) {
  wxLongLong oldTime = wxStartTime;
  wxLongLong newTime = wxGetLocalTimeMillis();
  if( resetTimer ) {
    wxStartTime = newTime;
  }
  return ( newTime - oldTime ).GetLo();
}

long wxGetLocalTime() {
  struct tm tm;
  time_t t0, t1;
  memset( &tm, 0, sizeof( tm ) );
  tm.tm_year  = 70;
  tm.tm_mon   = 0;
  tm.tm_mday  = 5;        // not Jan 1st 1970 due to mktime 'feature'
  tm.tm_hour  = 0;
  tm.tm_min   = 0;
  tm.tm_sec   = 0;
  tm.tm_isdst = -1;       // let mktime guess
  t1 = time( &t1 );       // now
  t0 = mktime( &tm );     // origin
  // Return the difference in seconds.
  //
  if( ( t0 != ( time_t ) - 1 ) && ( t1 != ( time_t ) - 1 ) ) {
    return ( long )difftime( t1, t0 ) + ( 60 * 60 * 24 * 4 );
  }
  wxLogSysError( _( "Failed to get the local system time" ) );
  return -1;
}

// Get UTC time as seconds since 00:00:00, Jan 1st 1970
long wxGetUTCTime() {
  return ( long )time( NULL );
}

wxLongLong wxGetLocalTimeMillis() {
  wxLongLong val = 1000l;
  struct timeval tp;
  if( wxGetTimeOfDay( &tp, ( struct timezone * )NULL ) != -1 ) {
    val *= tp.tv_sec;
    return ( val + ( tp.tv_usec / 1000 ) );
  } else {
    wxLogError( _( "wxGetTimeOfDay failed." ) );
    return 0;
  }
}
